import { InjectRepository } from '@nestjs/typeorm';
import { OrderEntity } from './entities/order.entity';
import { In, Repository } from 'typeorm';
import { OrderItemEntity } from './entities/order-item.entity';
import { CartEntity } from '../cart/entities/shop-cart.entity';
import { CreateCartDto } from '../cart/dto/shop-cart.dto';
import { BadRequestException, Inject } from '@nestjs/common';
import { AddressService } from '../address/address.service';
import { CreateCartOrderDto, CreateDirectOrderDto, QueryOrder } from './dto/order.dto';
import { ResultData } from 'src/common/utils/result';
import { ProductEntity } from '../products/entities/shop-products.entity';

export class OrderService {
  constructor(
    @InjectRepository(OrderEntity)
    private readonly orderRepo: Repository<OrderEntity>,
    @InjectRepository(OrderItemEntity)
    private readonly orderItemRepo: Repository<OrderItemEntity>,
    @InjectRepository(CartEntity)
    private readonly cartRepo: Repository<CartEntity>,
    @InjectRepository(ProductEntity)
    private readonly productRepo: Repository<ProductEntity>,
    @Inject()
    private readonly addressService: AddressService,
  ) {}

  //生成订单号
  private generateOrderSn(): string {
    return 'OD' + Date.now() + Math.floor(Math.random() * 1000);
  }

  //购物车下单
  async createCartOrder(userId: number, dto: CreateCartOrderDto) {
    const { addressId, cartIds } = dto;
    //查询购物车中商品
    const carts = await this.cartRepo.find({
      where: { id: In(cartIds), userId },
    });
    if (carts.length === 0) throw new BadRequestException('购物车为空');

    //查询收货地址
    const { data: address } = await this.addressService.findOne(addressId, userId);
    if (!address) throw new BadRequestException('无效的收货地址');

    //计算总价
    const totalAmount = carts.reduce((sum, cur) => sum + Number(cur.price) * cur.quantity, 0);

    //创建订单主表
    const order = this.orderRepo.create({
      orderNo: this.generateOrderSn(),
      userId,
      totalAmount,
      addressSnapshot: JSON.stringify(address),
      status: 'unpaid',
    });
    await this.orderRepo.save(order);

    const items = carts.map((c) =>
      this.orderItemRepo.create({
        orderId: order.id,
        productId: c.productId,
        productName: c.productName,
        price: c.price,
        quantity: c.quantity,
        image: c.image,
      }),
    );
    await this.orderItemRepo.save(items);

    //删除购物车项
    await this.cartRepo.delete({ id: In(cartIds) });

    return ResultData.ok({ orderId: order.id, orderNo: order.orderNo, totalAmount });
  }

  //立即购买下单
  async createDirectOrder(userId: number, dto: CreateDirectOrderDto) {
    const { productId, quantity, addressId } = dto;

    //查询商品
    const product = await this.productRepo.findOne({ where: { id: productId } });
    if (!product) throw new BadRequestException('商品不存在');

    //查地址
    const { data: address } = await this.addressService.findOne(addressId, userId);
    if (!address) throw new BadRequestException('无效的收货地址');
    // 3. 计算总价
    const totalAmount = Number(product.price) * quantity;

    //创建主订单
    const order = await this.orderRepo.create({
      orderNo: this.generateOrderSn(),
      userId,
      totalAmount,
      addressSnapshot: JSON.stringify(address),
      status: 'unpaid',
    });

    await this.orderRepo.save(order);

    //创建订单明细
    const items = this.orderItemRepo.create({
      orderId: order.id,
      productId: product.id,
      productName: product.name,
      price: product.price,
      quantity: quantity,
      image: product.mainImage,
    });

    await this.orderItemRepo.save(items);

    return ResultData.ok({ orderId: order.id, orderNo: order.orderNo, totalAmount });
  }

  async orderList(userId: number, dto: QueryOrder) {
    const { status = null, pageNum, pageSize } = dto;
    const queryBuilder = this.orderRepo.createQueryBuilder('o').leftJoinAndSelect('o.items', 'item').where('o.userId=:userId', { userId });
    if (status) queryBuilder.andWhere('o.status=:status', { status });
    if (pageNum && pageSize) {
      queryBuilder.skip(pageSize * (pageNum - 1)).take(pageSize);
    }
    const [list, total] = await queryBuilder.getManyAndCount();
    return ResultData.ok({
      list,
      total,
    });
  }
}
